為了程式效率,通常會利用記憶體存取速度遠高於磁碟讀取的特性,把常用但不常變動資料放在記憶體中,提升取用資料的速度。ASP.NET Core 有提供好用的快取機制,不用自己實作控制資料的快取物件。
本篇將介紹 ASP.NET Core 的本機快取及分散式快取,並用使用分散式快取實作 Redis Session,避免 Web Application 重啟後,用戶要重新登入。
同步發佈至個人部落格:
John Wu's Blog - [鐵人賽 Day20] ASP.NET Core 2 系列 - 快取機制及 Redis Session
本機快取是比較基本的資料快取方式,將資料存在 Web Application 的記憶體中。
如果是單一站台架構,沒有要同步快取資料,用本機快取應該都能滿足需求。
使用本機快取的方式很簡單,只要在 Startup.ConfigureServices
呼叫 AddMemoryCache
,就能透過注入 IMemoryCache
使用本機快取。如下:
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
// ...
}
//...
}
Controllers\HomeController.cs
using Microsoft.Extensions.Caching.Memory;
//...
public class HomeController : Controller
{
private static IMemoryCache _memoryCache;
public HomeController(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public IActionResult Index()
{
_memoryCache.Set("Sample", new UserModel()
{
Id = 1,
Name = "John"
});
var model = _memoryCache.Get<UserModel>("Sample");
return View(model);
}
}
用 Get
/Set
方法,就可以透過 Key 做為取值的識別,存放任何型別的資料。
當 ASP.NET Core 網站有橫向擴充,架設多個站台需求時,分散式快取就是一個很好的同步快取資料解決方案。
基本上就是 NoSQL 的概念,把分散式快取的資料位置,指向外部的儲存空間,如:SQL Server、Redis 等等。只要繼承 IDistributedCache
,就可以被當作分散式快取的服務使用。
本機快取及分散式快取架構,如圖:
在 Startup.ConfigureServices
注入 IDistributedCache
使用分散式快取。如下:
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
// ...
}
//...
}
IDistributedCache
,將資料存於本機記憶體中。Controllers\HomeController.cs
using Microsoft.Extensions.Caching.Distributed;
//...
public class HomeController : Controller
{
private static IDistributedCache _distributedCache;
public HomeController(IDistributedCache distributedCache)
{
_distributedCache = distributedCache;
}
public IActionResult Index()
{
_distributedCache.Set("Sample", ObjectToByteArray(new UserModel()
{
Id = 1,
Name = "John"
}));
var model = ByteArrayToObject<UserModel>(_distributedCache.Get("Sample"));
return View(model);
}
private byte[] ObjectToByteArray(object obj)
{
var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, obj);
return memoryStream.ToArray();
}
}
private T ByteArrayToObject<T>(byte[] bytes)
{
using (var memoryStream = new MemoryStream())
{
var binaryFormatter = new BinaryFormatter();
memoryStream.Write(bytes, 0, bytes.Length);
memoryStream.Seek(0, SeekOrigin.Begin);
var obj = binaryFormatter.Deserialize(memoryStream);
return (T)obj;
}
}
}
IDistributedCache
的 Get
/Set
不像 IMemoryCache
可以存取任意型別,IDistributedCache
的 Get
/Set
只能存取 byte[]
型別,如果要將物件存入分散式快取,就必須將物件轉換成 byte[]
型別,或轉成字串型別用 GetString
/SetString
存取於分散式快取。
如果要將物件透過
MemoryStream
序列化,記得在物件加上[Serializable]
。
[Day11] ASP.NET Core 2 系列 - Cookies & Session 有用到 AddDistributedMemoryCache
,由於 Session 的儲存位置是依賴分散式快取,但沒有外部分散式快取可用,所以用繼承 IDistributedCache
的本機分散式快取頂著。
如果要在 ASP.NET Core 中使用的 Redis Cache,可以安裝 Microsoft 提供的套件 Microsoft.Extensions.Caching.Redis.Core
。
透過 .NET Core CLI 在專案資料夾執行安裝指令:
dotnet add package Microsoft.Extensions.Caching.Redis.Core
安裝完成後,將 Startup.ConfigureServices
註冊的分散式快取服務,從 AddDistributedMemoryCache
改成 AddDistributedRedisCache
。如下:
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//services.AddDistributedMemoryCache();
services.AddDistributedRedisCache(options =>
{
// Redis Server 的 IP 跟 Port
options.Configuration = "192.168.99.100:6379";
});
// ...
}
//...
}
這樣就完成將分散式快取指向 Redis Cache,Session 的註冊方式同 [Day11] 。
只要設定 AddDistributedRedisCache
就可以使用 Redis Session 了,輕鬆簡單。
ASP.NET Core 的 Redis Session 跟 ASP.NET MVC 普遍用的 StackExchange.Redis
的運行方式有很大的差異。
ASP.NET MVC Redis Session
StackExchange.Redis
在使用 Redis 時,是把 Website 的 Session 備份到 Redis,讀取還是在 Website 的記憶體,寫入的話會再度備份到 Redis。
也就是說 Session 會存在於 Website 及 Redis Cache 中,HA 的概念。
可以試著把 Redis Cache 中 Session 清掉,當使用者下一個 Requset 來的時候,又會重新出現在 Redis Cache 中。
運行方式如下圖:
ASP.NET Core Redis Session
IDistributedCache
運作方式變成 Session 直接在 Redis Cache 存取,如果把 Redis Cache 中 Session 清掉,當使用者下一個 Requset 來的時候,就會發現 Session 被清空了。
運行方式如下圖:
In-memory caching in ASP.NET Core
Working with a distributed cache in ASP.NET Core
您好
我想詢問最後 ASP.NET Core Redis Session
示意圖似乎是不對的?
(部落格的文章也有一樣情形)
你指哪方面不對?
抱歉, 我又看了數次看懂了
另外瞄到一個錯字
IDistributedCache 運'做'方式變成 Session 直接在 Redis Cache 存取
太強大的眼力了~感謝校稿